home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / fix.c < prev    next >
C/C++ Source or Header  |  1990-07-19  |  5KB  |  206 lines

  1. /* fix file difflist - update file from difflist     Author: Erik Baalbergen */
  2.  
  3.  
  4. /* Notes: files old and old.patch are equal after the following commands
  5.      diff old new > difflist
  6.      patch old difflist > old.patch
  7.    * the diff output is assumed to be produced by my diff program.
  8.    * the difflist has the following form:
  9.      difflist ::= chunk*
  10.      chunk ::= append | delete | change ;
  11.      append ::= n1 'a' n2 [',' n3]? '\n' ['> ' line '\n'](n3 - n2 + 1)
  12.      delete ::= n1 [',' n2]? 'd' n3 '\n' ['< ' line '\n'](n2 - n1 + 1)
  13.      change ::= n1 [',' n2]? 'c' n3 [',' n4]? '\n'
  14.           ['< ' line '\n'](n2 - n1 + 1)
  15.           '---\n'
  16.           ['> ' line '\n'](n4 - n3 + 1)
  17.      where
  18.      - n[1234] is an unsigned integer
  19.      - "[pat](expr)" means "(expr) occurences of pat"
  20.      - "[pat]?" means "either pat or nothing"
  21.    * the information in the diff listing is checked against the file to which
  22.      it is applied; an error is printed if there is a conflict
  23. */
  24.  
  25. #include <stdio.h>
  26.  
  27. #define IGNORE_WHITE_SPACE    /* This makes it white space insensitive */
  28.  
  29. #ifdef IGNORE_WHITE_SPACE
  30. #define strcmp strwcmp
  31. #endif
  32.  
  33. extern char *fgets();
  34. extern FILE *fopen();
  35. #define LINELEN    1024
  36.  
  37. char *prog = 0, *processing = 0;
  38.  
  39. char *
  40.  getline(fp, b)
  41. FILE *fp;
  42. char *b;
  43. {
  44.   int slen;
  45.   if (fgets(b, LINELEN, fp) == NULL) fatal("unexpected eof");
  46.  
  47.   return b;
  48. }
  49.  
  50. #define copy(str) printf("%s", str)
  51.  
  52. main(argc, argv)
  53. char **argv;
  54. {
  55.   char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN];
  56.   int o1, o2, n1, n2, here;
  57.   FILE *fpf, *fpd;
  58.  
  59.   prog = argv[0];
  60.   processing = argv[1];
  61.   if (argc != 3) fatal("use: %s original-file diff-list-file", prog);
  62.   if ((fpf = fopen(argv[1], "r")) == NULL) fatal("can't read %s", argv[1]);
  63.   if ((fpd = fopen(argv[2], "r")) == NULL) fatal("can't read %s", argv[2]);
  64.   here = 0;
  65.   while (getcommand(fpd, &o1, &o2, &cmd, &n1, &n2)) {
  66.     while (here < o1 - 1) {
  67.         here++;
  68.         copy(getline(fpf, obuf));
  69.     }
  70.     switch (cmd) {
  71.         case 'c':
  72.         case 'd':
  73.         if (cmd == 'd' && n1 != n2) fatal("delete count conflict");
  74.         while (o1 <= o2) {
  75.             fl = getline(fpf, obuf);
  76.             here++;
  77.             fd = getline(fpd, nbuf);
  78.             if (strncmp(fd, "<", 1))
  79.                 fatal("illegal delete line");
  80.             if (strcmp(fl, fd + 2))
  81.                 fatal("delete line conflict");
  82.             o1++;
  83.         }
  84.         if (cmd == 'd') break;
  85.         if (strcmp(getline(fpd, nbuf), "---\n"))
  86.             fatal("illegal separator in chunk");
  87.         /* FALLTHROUGH */
  88.         case 'a':
  89.         if (cmd == 'a') {
  90.             if (o1 != o2) fatal("append count conflict");
  91.             copy(getline(fpf, obuf));
  92.             here++;
  93.         }
  94.         while (n1 <= n2) {
  95.             if (strncmp(getline(fpd, nbuf), ">", 1))
  96.                 fatal("illegal append line");
  97.             copy(nbuf + 2);
  98.             n1++;
  99.         }
  100.         break;
  101.     }
  102.   }
  103.   while (fgets(obuf, LINELEN, fpf) != NULL) copy(obuf);
  104.   exit(0);
  105. }
  106.  
  107. isdigit(c)
  108. char c;
  109. {
  110.   return c >= '0' && c <= '9';
  111. }
  112.  
  113. char *
  114.  range(s, p1, p2)
  115. char *s;
  116. int *p1, *p2;
  117. {
  118.   register int v1 = 0, v2;
  119.  
  120.   while (isdigit(*s)) v1 = 10 * v1 + *s++ - '0';
  121.   v2 = v1;
  122.   if (*s == ',') {
  123.     s++;
  124.     v2 = 0;
  125.     while (isdigit(*s)) v2 = 10 * v2 + *s++ - '0';
  126.   }
  127.   if (v1 > v2) fatal("illegal range");
  128.   *p1 = v1;
  129.   *p2 = v2;
  130.   return s;
  131. }
  132.  
  133. getcommand(fp, o1, o2, pcmd, n1, n2)
  134. FILE *fp;
  135. int *o1, *o2, *n1, *n2;
  136. char *pcmd;
  137. {
  138.   char buf[LINELEN];
  139.   register char *s;
  140.   char cmd;
  141.  
  142.   if ((s = fgets(buf, LINELEN, fp)) == NULL) return 0;
  143.   s = range(s, o1, o2);
  144.   if ((cmd = *s++) != 'a' && cmd != 'c' && cmd != 'd')
  145.     fatal("illegal command");
  146.   s = range(s, n1, n2);
  147.   if (*s != '\n' && s[1] != '\0')
  148.     fatal("extra characters at end of command: %s", s);
  149.   *pcmd = cmd;
  150.   return 1;
  151. }
  152.  
  153. fatal(s, a)
  154. char *s, *a;
  155. {
  156.   fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
  157.   fprintf(stderr, s, a);
  158.   fprintf(stderr, "\n");
  159.   exit(1);
  160. }
  161.  
  162. #ifdef IGNORE_WHITE_SPACE
  163.  
  164. /* This routine is a white space insensitive version of strcmp.
  165.    It is needed for testing things which might have undergone
  166.    tab conversion or trailing space removal
  167.    Bret Mckee June, 1988 */
  168.  
  169. int strwcmp(s1, s2)
  170. char *s1, *s2;
  171. {
  172.   char *x1 = s1, *x2 = s2;
  173.  
  174.   /* Remove leading white space */
  175.   while (whitespace(*s1)) s1++;
  176.   while (whitespace(*s2)) s2++;
  177.   do {
  178.     while ((*s1 == *s2) && *s1 && *s2) {
  179.         s1++;
  180.         s2++;
  181.     }
  182.     ;            /* consume identical characters */
  183.     while (whitespace(*s1)) s1++;
  184.     while (whitespace(*s2)) s2++;
  185.   } while (*s1 && *s2 && (*s1 == *s2));
  186.   if (*s1 - *s2)
  187.     fprintf(stderr, "Failing for (%x)[%s]\n            (%x)[%s]\n",
  188.         (int) *s1, x1, (int) *s2, x2);
  189.   return(*s1 - *s2);
  190. }
  191.  
  192. int whitespace(ch)
  193. char ch;
  194. {
  195.   switch (ch) {
  196.       case ' ':
  197.       case '\n':
  198.       case 0x0D:
  199.       case '\t':
  200.     return(1);
  201.       default:    return(0);
  202. }
  203. }
  204.  
  205. #endif
  206.